package com.sugar.subscribe.course.module.business.dal.mysql.order;

import cn.hutool.core.util.StrUtil;
import com.sugar.subscribe.course.framework.common.pojo.PageResult;
import com.sugar.subscribe.course.framework.mybatis.core.mapper.BaseMapperX;
import com.sugar.subscribe.course.framework.mybatis.core.query.MPJLambdaWrapperX;
import com.sugar.subscribe.course.module.business.controller.app.coachwallet.vo.AppCoachProfitHistoryRespVO;
import com.sugar.subscribe.course.module.business.controller.app.order.vo.AppOrderPageReqVO;
import com.sugar.subscribe.course.module.business.controller.app.order.vo.AppUserOrderPageRespVO;
import com.sugar.subscribe.course.module.business.dal.dataobject.coach.CoachDO;
import com.sugar.subscribe.course.module.business.dal.dataobject.order.OrderDO;
import com.sugar.subscribe.course.module.business.dal.dataobject.user.BizUserDO;
import com.sugar.subscribe.course.module.business.enums.order.OrderEnum;
import com.sugar.subscribe.course.module.business.job.order.dto.OrderCommissionSharingDTO;
import com.sugar.subscribe.course.module.business.job.order.dto.OrderConfirmDTO;
import org.apache.ibatis.annotations.Mapper;
import com.sugar.subscribe.course.module.business.controller.admin.order.vo.*;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import java.util.List;

/**
 * 订单 Mapper
 *
 * @author Ysugar
 */
@Mapper
public interface BizOrderMapper extends BaseMapperX<OrderDO> {

    default PageResult<OrderRespVO> selectPage(OrderPageReqVO reqVO) {
        MPJLambdaWrapperX<OrderDO> wrapper = new MPJLambdaWrapperX<>();
        wrapper
                .selectAll(OrderDO.class)
                .selectAs(CoachDO::getName, OrderRespVO::getCoachName)
                .selectAs(CoachDO::getMobile, OrderRespVO::getCoachMobile)
                .leftJoin(CoachDO.class, CoachDO::getId, OrderDO::getCoachId);

        Long[] serviceIds = reqVO.getServiceIds();
        if (serviceIds != null){
            switch (serviceIds.length){
                case 2:
                    wrapper.eq(OrderDO::getServiceId, serviceIds[1]);
                case 1:
                    wrapper.eq(OrderDO::getServicePId, serviceIds[0]);
            }
        }
        return selectJoinPage(reqVO, OrderRespVO.class, wrapper
                .eqIfPresent(OrderDO::getUserId, reqVO.getUserId())
                .eqIfPresent(OrderDO::getOrderNo, reqVO.getOrderNo())
                .eqIfPresent(OrderDO::getCoachId, reqVO.getCoachId())
                .likeIfPresent(OrderDO::getNickname, reqVO.getNickname())
                .eqIfPresent(OrderDO::getMobile, reqVO.getMobile())
                .eqIfPresent(OrderDO::getVenueId, reqVO.getVenueId())
                .betweenIfPresent(OrderDO::getOrderTime, reqVO.getOrderTime())
                .eqIfPresent(OrderDO::getPaymentStatus, reqVO.getPaymentStatus())
                .betweenIfPresent(OrderDO::getPaymentTime, reqVO.getPaymentTime())
                .eqIfPresent(OrderDO::getCancelType, reqVO.getCancelType())
                .eqIfPresent(OrderDO::getStatus, reqVO.getStatus())
                .eqIfPresent(OrderDO::getRefundStatus, reqVO.getRefundStatus())
                .betweenIfPresent(OrderDO::getCreateTime, reqVO.getCreateTime())
                .orderByDesc(OrderDO::getId));
    }

    default PageResult<AppUserOrderPageRespVO> appGetUserOrderPage(AppOrderPageReqVO reqVO, Long userId, Long coachId, Boolean noPay){
        String content = reqVO.getContent();
        return selectJoinPage(reqVO, AppUserOrderPageRespVO.class, new MPJLambdaWrapperX<OrderDO>()
                .selectAs(OrderDO::getId, AppUserOrderPageRespVO::getId)
                .selectAs(OrderDO::getOrderNo, AppUserOrderPageRespVO::getOrderNo)
                .selectAs(OrderDO::getCoachId, AppUserOrderPageRespVO::getCoachId)
                .selectAs(OrderDO::getAttendClassDate, AppUserOrderPageRespVO::getAttendClassDate)
                .selectAs(OrderDO::getVenueName, AppUserOrderPageRespVO::getVenueName)
                .selectAs(OrderDO::getServicePName, AppUserOrderPageRespVO::getServicePName)
                .selectAs(OrderDO::getServiceName, AppUserOrderPageRespVO::getServiceName)
                .selectAs(OrderDO::getStartTime, AppUserOrderPageRespVO::getStartTime)
                .selectAs(OrderDO::getPeopleCount, AppUserOrderPageRespVO::getPeopleCount)
                .selectAs(OrderDO::getServiceTime, AppUserOrderPageRespVO::getServiceTime)
                .selectAs(OrderDO::getUpdatedAttendClassDate, AppUserOrderPageRespVO::getUpdatedAttendClassDate)
                .selectAs(OrderDO::getPaymentStatus, AppUserOrderPageRespVO::getPaymentStatus)
                .selectAs(OrderDO::getStatus, AppUserOrderPageRespVO::getStatus)
                .eqIfPresent(OrderDO::getStatus, reqVO.getStatus())
                .eqIfPresent(OrderDO::getVenueId, reqVO.getVenueId())
                .eqIfPresent(OrderDO::getServiceId, reqVO.getServiceId())
                .eqIfPresent(OrderDO::getAttendClassDate, reqVO.getAttendClassDate())
                .eqIfPresent(OrderDO::getUserId, userId)
                .eqIfPresent(OrderDO::getCoachId, coachId)
                .eq(noPay, OrderDO::getPaymentStatus, 1)
                .nested(StrUtil.isNotBlank(content),
                        w -> w.like(OrderDO::getVenueName, content)
                                .or().like(OrderDO::getServicePName, content)
                                .or().like(OrderDO::getServiceName, content))
                .orderByDesc(OrderDO::getId));
    }

    @Select("<script>" +
            "select" +
            " count(1) " +
            "from" +
            " (select" +
            "   DATE_FORMAT(bo.profit_arrival_time, '%Y-%m-%d') AS formatted_date " +
            "  from business_order bo " +
            "  left join business_user bu on bo.user_id = bu.id and bu.deleted = 0 " +
            "  where bo.deleted = 0 and bo.status = 4 and bo.coach_id = #{param1} " +
            "  <if test=\"param2 != null and param2 != ''\"> and (bu.mobile like concat('%', #{param2}, '%') or bo.order_no like concat('%', #{param2}, '%'))</if>" +
            "  group by formatted_date " +
            "  order by formatted_date desc) tmp_tbl " +
            "where tmp_tbl.formatted_date is not null" +
            "</script>")
    long selectProfitHistoryDatePageCount(Long coachId, String search);

    @Select("<script>" +
            "select" +
            " tmp_tbl.formatted_date as date " +
            "from" +
            " (select" +
            "   DATE_FORMAT(bo.profit_arrival_time, '%Y-%m-%d') AS formatted_date " +
            "  from business_order bo " +
            "  left join business_user bu on bo.user_id = bu.id and bu.deleted = 0 " +
            "  where bo.deleted = 0 and bo.status = 4 and bo.coach_id = #{param1} " +
            "  <if test=\"param2 != null and param2 != ''\"> and (bu.mobile like concat('%', #{param2}, '%') or bo.order_no like concat('%', #{param2}, '%'))</if>" +
            "  group by formatted_date " +
            "  order by formatted_date desc) tmp_tbl " +
            "where tmp_tbl.formatted_date is not null " +
            "limit #{param3}, #{param4}" +
            "</script>")
    List<AppCoachProfitHistoryRespVO> selectProfitHistoryDatePage(Long coachId, String search, Integer skipCount, Integer pageSize);

    default List<AppCoachProfitHistoryRespVO.DateData> getCoachProfitHistoryList(Long coachId, String search, String date){
        return selectJoinList(AppCoachProfitHistoryRespVO.DateData.class, new MPJLambdaWrapperX<OrderDO>()
                .selectAs(BizUserDO::getAvatar, AppCoachProfitHistoryRespVO.DateData::getUserAvatar)
                .selectAs(BizUserDO::getMobile, AppCoachProfitHistoryRespVO.DateData::getUserMobile)
                .selectAs(OrderDO::getOrderNo, AppCoachProfitHistoryRespVO.DateData::getOrderNo)
                .selectAs(OrderDO::getServiceName, AppCoachProfitHistoryRespVO.DateData::getServiceName)
                .selectAs(OrderDO::getProfitAmount, AppCoachProfitHistoryRespVO.DateData::getProfitAmount)
                .selectAs(OrderDO::getOrderTime, AppCoachProfitHistoryRespVO.DateData::getOrderTime)
                .selectAs(OrderDO::getAttendClassTime, AppCoachProfitHistoryRespVO.DateData::getAttendClassTime)
                .selectAs(OrderDO::getProfitArrivalTime, AppCoachProfitHistoryRespVO.DateData::getProfitArrivalTime)
                .leftJoin(BizUserDO.class, BizUserDO::getId, OrderDO::getUserId)
                .eqIfPresent(OrderDO::getCoachId, coachId)
                .eqIfPresent(OrderDO::getStatus, OrderEnum.DONE.getStatus())
                .betweenIfPresent(OrderDO::getProfitArrivalTime, date + " 00:00:00", date + " 23:59:59")
                .nested(StrUtil.isNotBlank(search), w -> w
                        .like(OrderDO::getOrderNo, search).or()
                        .like(OrderDO::getMobile, search))
                .orderByDesc(OrderDO::getId)
        );
    }

    @Select("select" +
            " if(tbl.payment_amount is not null, tbl.payment_amount, 0) - if(tbl.profit_amount is not null, tbl.profit_amount, 0) " +
            "from" +
            " (select" +
            "   sum(bo.payment_amount) payment_amount, sum(bo.profit_amount) profit_amount" +
            "  from business_order bo " +
            "  where bo.deleted = 0 and bo.payment_status = 1 and bo.refund_status = 0 and bo.status = 4) tbl")
    Integer selectGrossProfit();

    // 直接更新，暂时无用
    @Update("update" +
            " business_order bo " +
            "set bo.status = 4, bo.done_time = CURRENT_TIMESTAMP() " +
            "where bo.deleted = 0" +
            " and bo.status = 3" +
            " and bo.payment_status = 1" +
            " and bo.refund_status = 0" +
            " and bo.cancel_type = 0" +
            " and TIMESTAMPDIFF(DAY, bo.attend_class_time, CURRENT_TIMESTAMP()) >= 3")
    long autoConfirmOrder();

    @Select("select" +
            " bo.id, bo.payment_amount, bc.commission_rate " +
            "from business_order bo " +
            "left join business_coach bc on bo.coach_id = bc.id and bc.deleted = 0 " +
            "where bo.deleted = 0" +
            " and bo.status = 3" +
            " and bo.payment_status = 1" +
            " and bo.refund_status = 0" +
            " and bo.cancel_type = 0 and TIMESTAMPDIFF(DAY, bo.attend_class_time, CURRENT_TIMESTAMP()) >= 3")
    List<OrderConfirmDTO> selectAutoConfirmOrderIds();

    @Select("select bo.id, bo.coach_id, bo.profit_amount " +
            "from business_order bo " +
            "where bo.deleted = 0" +
            " and bo.status = 4" +
            " and bo.profit_arrival_status = 0" +
            " and bo.payment_status = 1" +
            " and bo.refund_status = 0" +
            " and bo.cancel_type = 0" +
            " and TIMESTAMPDIFF(DAY, bo.done_time, CURRENT_TIMESTAMP()) >= 1")
    List<OrderCommissionSharingDTO> selectNotCommissionSharingOrder();
}